home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 5 / Example 5.6 / app.cpp next >
Encoding:
C/C++ Source or Header  |  2006-08-01  |  7.7 KB  |  300 lines

  1. //////////////////////////////////////////////////////////////
  2. // Example 5.6: Frustum Culling                                //
  3. // Written by: C. Granberg, 2006                            //
  4. //////////////////////////////////////////////////////////////
  5.  
  6. #include <windows.h>
  7. #include <d3dx9.h>
  8. #include <vector>
  9. #include "debug.h"
  10. #include "mouse.h"
  11. #include "object.h"
  12. #include "camera.h"
  13. #include "city.h"
  14.  
  15. class APPLICATION
  16. {
  17.     public:
  18.         APPLICATION();
  19.         HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
  20.         HRESULT Update(float deltaTime);
  21.         HRESULT Render();
  22.         HRESULT Cleanup();
  23.         HRESULT Quit();
  24.  
  25.     private:
  26.         IDirect3DDevice9* m_pDevice; 
  27.         CITY m_city;
  28.         MOUSE m_mouse;
  29.         CAMERA m_camera;
  30.  
  31.         ID3DXLine *m_pLine;
  32.         D3DLIGHT9 m_light;
  33.         HWND m_mainWindow;
  34.         ID3DXFont *m_pFont;
  35. };
  36.  
  37. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  38. {
  39.     APPLICATION app;
  40.  
  41.     if(FAILED(app.Init(hInstance, 800, 600, true)))
  42.         return 0;
  43.  
  44.     MSG msg;
  45.     memset(&msg, 0, sizeof(MSG));
  46.     int startTime = timeGetTime(); 
  47.  
  48.     while(msg.message != WM_QUIT)
  49.     {
  50.         if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  51.         {
  52.             ::TranslateMessage(&msg);
  53.             ::DispatchMessage(&msg);
  54.         }
  55.         else
  56.         {    
  57.             int t = timeGetTime();
  58.             float deltaTime = (t - startTime)*0.001f;
  59.  
  60.             app.Update(deltaTime);
  61.             app.Render();
  62.  
  63.             startTime = t;
  64.         }
  65.     }
  66.  
  67.     app.Cleanup();
  68.  
  69.     return msg.wParam;
  70. }
  71.  
  72. APPLICATION::APPLICATION()
  73. {
  74.     m_pDevice = NULL; 
  75.     m_mainWindow = 0;
  76.     m_pFont = NULL;
  77.     m_pLine = NULL;
  78.  
  79.     srand(GetTickCount());
  80. }
  81.  
  82. HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
  83. {
  84.     debug.Print("Application initiated");
  85.  
  86.     //Create Window Class
  87.     WNDCLASS wc;
  88.     memset(&wc, 0, sizeof(WNDCLASS));
  89.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  90.     wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 
  91.     wc.hInstance     = hInstance;
  92.     wc.lpszClassName = "D3DWND";
  93.  
  94.     //Register Class and Create new Window
  95.     RegisterClass(&wc);
  96.     m_mainWindow = CreateWindow("D3DWND", "Example 5.6: Frustum Culling", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0); 
  97.     SetCursor(NULL);
  98.     ShowWindow(m_mainWindow, SW_SHOW);
  99.     UpdateWindow(m_mainWindow);
  100.  
  101.     //Create IDirect3D9 Interface
  102.     IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  103.  
  104.     if(d3d9 == NULL)
  105.     {
  106.         debug.Print("Direct3DCreate9() - FAILED");
  107.         return E_FAIL;
  108.     }
  109.  
  110.     //Check that the Device supports what we need from it
  111.     D3DCAPS9 caps;
  112.     d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  113.  
  114.     //Hardware Vertex Processing or not?
  115.     int vp = 0;
  116.     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  117.         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  118.     else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  119.  
  120.     //Check vertex & pixelshader versions
  121.     if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
  122.     {
  123.         debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
  124.     }
  125.  
  126.     //Set D3DPRESENT_PARAMETERS
  127.     D3DPRESENT_PARAMETERS d3dpp;
  128.     d3dpp.BackBufferWidth            = width;
  129.     d3dpp.BackBufferHeight           = height;
  130.     d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
  131.     d3dpp.BackBufferCount            = 1;
  132.     d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
  133.     d3dpp.MultiSampleQuality         = 0;
  134.     d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
  135.     d3dpp.hDeviceWindow              = m_mainWindow;
  136.     d3dpp.Windowed                   = windowed;
  137.     d3dpp.EnableAutoDepthStencil     = true; 
  138.     d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
  139.     d3dpp.Flags                      = 0;
  140.     d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  141.     d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  142.  
  143.     //Create the IDirect3DDevice9
  144.     if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
  145.                                  vp, &d3dpp, &m_pDevice)))
  146.     {
  147.         debug.Print("Failed to create IDirect3DDevice9");
  148.         return E_FAIL;
  149.     }
  150.  
  151.     //Release IDirect3D9 interface
  152.     d3d9->Release();
  153.  
  154.     D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
  155.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  156.                    DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);
  157.  
  158.     //Create m_light
  159.     ::ZeroMemory(&m_light, sizeof(m_light));
  160.     m_light.Type      = D3DLIGHT_DIRECTIONAL;
  161.     m_light.Ambient   = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  162.     m_light.Diffuse   = D3DXCOLOR(0.9, 0.9, 0.9, 1.0f);
  163.     m_light.Specular  = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  164.     m_light.Direction = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
  165.     m_pDevice->SetLight(0, &m_light);
  166.     m_pDevice->LightEnable(0, true);
  167.  
  168.     //Set sampler state
  169.     for(int i=0;i<4;i++)
  170.     {
  171.         m_pDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  172.         m_pDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  173.         m_pDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  174.     }
  175.  
  176.     //Init camera
  177.     m_camera.Init(m_pDevice);    
  178.  
  179.     //Load objects
  180.     LoadObjectResources(m_pDevice);
  181.  
  182.     //Create 2D Line
  183.     D3DXCreateLine(m_pDevice, &m_pLine);
  184.  
  185.     //Create city
  186.     m_city.Init(INTPOINT(25, 25));
  187.     m_camera.m_focus = m_city.GetCenter();
  188.  
  189.     //Init mouse
  190.     m_mouse.InitMouse(m_pDevice, m_mainWindow);
  191.  
  192.     return S_OK;
  193. }
  194.  
  195. HRESULT APPLICATION::Update(float deltaTime)
  196. {
  197.     //Control camera
  198.     D3DXMATRIX  matWorld;
  199.     D3DXMatrixIdentity(&matWorld);
  200.     m_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
  201.  
  202.     //Update mouse
  203.     m_mouse.Update();
  204.  
  205.     //Update camera
  206.     m_camera.Update(m_mouse, deltaTime);
  207.  
  208.     if(KEYDOWN(VK_ESCAPE))
  209.         Quit();
  210.  
  211.     return S_OK;
  212. }    
  213.  
  214.  
  215. HRESULT APPLICATION::Render()
  216. {
  217.     //Setup the viewport
  218.     D3DVIEWPORT9 v, v2;
  219.     v.Width = 800;
  220.     v.Height = 600;
  221.     v.X = 0;
  222.     v.Y = 0;
  223.     v.MaxZ = 1.0f;
  224.     v.MinZ = 0.0f;
  225.     m_pDevice->SetViewport(&v);
  226.     v2 = v;
  227.  
  228.     // Clear the viewport
  229.     m_pDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff4444ff, 1.0f, 0L );
  230.  
  231.     // Begin the scene 
  232.     if(SUCCEEDED(m_pDevice->BeginScene()))
  233.     {
  234.         //Render big city
  235.         m_city.Render(&m_camera);
  236.  
  237.         RECT r[] = {{10, 10, 0, 0}, {10, 30, 0, 0}, {10, 50, 0, 0}};
  238.         m_pFont->DrawText(NULL, "Mouse Wheel: Change Camera Radius", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  239.         m_pFont->DrawText(NULL, "Arrows: Change Camera Angle", -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  240.         
  241.         //Render city overview, set viewport
  242.         v.X = 550;
  243.         v.Y = 20;
  244.         v.Width = 230;
  245.         v.Height = 230;
  246.         m_pDevice->SetViewport(&v);
  247.         m_pDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L );
  248.  
  249.         //Setup camera view to orthogonal view looking down on city
  250.         D3DXMATRIX viewTop, projectionTop;
  251.         D3DXMatrixLookAtLH(&viewTop, &(m_city.GetCenter() + D3DXVECTOR3(0.0f, 100.0f, 0.0f)), &m_city.GetCenter(), &D3DXVECTOR3(0,0,1));
  252.         D3DXMatrixOrthoLH(&projectionTop, m_city.m_size.x * TILE_SIZE, m_city.m_size.y * TILE_SIZE, 0.1f, 1000.0f);
  253.         m_pDevice->SetTransform(D3DTS_VIEW, &viewTop);
  254.         m_pDevice->SetTransform(D3DTS_PROJECTION, &projectionTop);
  255.         
  256.         //Draw city blocks that are in view
  257.         m_city.Render(NULL);
  258.  
  259.         //Restore viewport
  260.         m_pDevice->SetViewport(&v2);
  261.  
  262.         //Draw line around smaller window
  263.         D3DXVECTOR2 outline[] = {D3DXVECTOR2(550, 20), D3DXVECTOR2(779, 20), D3DXVECTOR2(779, 249), D3DXVECTOR2(550, 249), D3DXVECTOR2(550, 20)};
  264.         m_pLine->SetWidth(3.0f);
  265.         m_pLine->Begin();
  266.         m_pLine->Draw(outline, 5, 0xff000000);
  267.         m_pLine->End();
  268.  
  269.         //Draw mouse
  270.         m_mouse.Paint();
  271.  
  272.         // End the scene.
  273.         m_pDevice->EndScene();
  274.         m_pDevice->Present(0, 0, 0, 0);
  275.     }
  276.  
  277.     return S_OK;
  278. }
  279.  
  280. HRESULT APPLICATION::Cleanup()
  281. {
  282.     try
  283.     {
  284.         m_pFont->Release();
  285.         m_pLine->Release();
  286.         m_pDevice->Release();
  287.  
  288.         debug.Print("Application terminated");
  289.     }
  290.     catch(...){}
  291.  
  292.     return S_OK;
  293. }
  294.  
  295. HRESULT APPLICATION::Quit()
  296. {
  297.     ::DestroyWindow(m_mainWindow);
  298.     ::PostQuitMessage(0);
  299.     return S_OK;
  300. }